import _ from 'lodash-es'

// 方法 - 获取坐标集最小覆盖圆（算法：最小圆覆盖-随即增量法）
type CenterCircleCoord = [number, number]
interface CenterCircleLine {
  from: string
  to: string
  coords: [CenterCircleCoord, CenterCircleCoord]
}
interface CenterCircle {
  center: CenterCircleCoord // 覆盖圆中心坐标
  radius: number // 半径（纬度为标准，1纬度=111KM）
  distance: number // 真实距离
  circleCoords: CenterCircleLine[] // 覆盖圆4个方向的切点
}
// 计算两点距离
function getDistanse(p1: CenterCircleCoord, p2: CenterCircleCoord): number {
  return Math.sqrt(
    (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1])
  )
}
// 计算两点中点
function getCenterPoint(p1: CenterCircleCoord, p2: CenterCircleCoord): CenterCircleCoord {
  return [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2]
}
// 计算3点定圆圆心
function getCircleBy3points(p1: CenterCircleCoord, p2: CenterCircleCoord, p3: CenterCircleCoord): CenterCircleCoord {
  const a1 = 2 * (p1[0] - p2[0])
  const b1 = 2 * (p1[1] - p2[1])
  const c1 = p1[0] * p1[0] - p2[0] * p2[0] + p1[1] * p1[1] - p2[1] * p2[1]
  const a2 = 2 * (p1[0] - p3[0])
  const b2 = 2 * (p1[1] - p3[1])
  const c2 = (p1[0] * p1[0] - p3[0] * p3[0] + p1[1] * p1[1] - p3[1] * p3[1])

  return [(b2 * c1 - b1 * c2) / (a1 * b2 - b1 * a2), (c1 * a2 - c2 * a1) / (b1 * a2 - a1 * b2)]
}
// 是否可以转为数字
function canToNumber(number: number | string) {
  return !isNaN(Number(number)) && number !== null
}
// 获取坐标集最小覆盖圆
export function getCenterCircle(coords: CenterCircleCoord[], defaultRadius = 0.2703): CenterCircle | undefined {
  if (!coords.length) {
    return
  }

  let center: CenterCircleCoord = [0, 0]
  let radius = 0
  let distance = 0
  let circleCoords: CenterCircleLine[] = []

  // 计算最小覆盖圆 圆心 + 半径
  if (coords.length === 1) {
    center = coords[0]
    radius = defaultRadius

  } else {
    const newCoords = _.shuffle(
      coords
      .filter(el => canToNumber(el[0]) && canToNumber(el[1]))
      .map((el): CenterCircleCoord => [el[0], el[1] * 1.3]) // 1纬度视觉长度=1.3经度，故进行视觉拉伸
    )

    let o = newCoords[0]
    let r = 0
    for (let i = 1; i < newCoords.length; i++) {
      if (getDistanse(newCoords[i], o) <= r) {
        continue
      }

      o = newCoords[i]
      r = 0

      for (let j = 0; j < i; j++) {
        if (getDistanse(newCoords[j], o) <= r) {
          continue
        }

        o = getCenterPoint(newCoords[j], newCoords[i])
        r = getDistanse(newCoords[j], newCoords[i]) / 2

        for (let k = 0; k < j; k++) {
          if (getDistanse(newCoords[k], o) <= r) {
            continue
          }

          o = getCircleBy3points(newCoords[i], newCoords[j], newCoords[k])
          r = getDistanse(newCoords[i], o)
        }
      }
    }

    center = [o[0], o[1] / 1.3]
    radius = r || defaultRadius // 点位列表坐标相同情况下半径为0，增加半径默认值
  }

  // 基于半径得出真实距离
  distance = radius * 111 || 30

  // 基于圆心和半径得出覆盖圆四个方向的切点
  const xRadius = radius * 1.05
  const yRadius = radius * 0.8

  const top: CenterCircleCoord = [center[0], center[1] + yRadius]
  const right: CenterCircleCoord = [center[0] + xRadius, center[1]]
  const bottom: CenterCircleCoord = [center[0], center[1] - yRadius]
  const left: CenterCircleCoord = [center[0] - xRadius, center[1]]

  circleCoords = [
    { from: '', to: '', coords: [top, right] },
    { from: '', to: '', coords: [right, bottom] },
    { from: '', to: '', coords: [bottom, left] },
    { from: '', to: '', coords: [left, top] },
  ]

  return {
    center,
    radius,
    distance,
    circleCoords
  }
}
